org 100h

;generate random number
mov 	ah, 2Ch
int 	21h
mov 	[random_number], dl

;print start message
push 	start_msg
call 	print_msg
;simulation of 16bit reg pop
add 	sp, 2

;loop until game ends
main_game_loop:

;ask for input from the user
push 	guess_request_msg
call 	print_msg
add 	sp, 2

;inc the rounds counter
inc 	byte [guess_counter]

;ax = two number digits from keyboard
call 	read_two_digits_number

;compare between the guess and the random number
cmp 	al,[random_number]
ja 		guess_is_higher
jb 		guess_is_lower

;print the beginning of the winning message
push 	win_msg_prefix
call 	print_msg
add 	sp, 2

;print number of attempts
mov 	ax,0
mov 	al, [guess_counter]
push 	ax
call 	print_number
add 	sp, 2

;print the end of the winning message
push 	win_msg_suffix
call 	print_msg
add 	sp, 2
jmp		end_of_program

;user guess higher number, print message and retry
guess_is_higher:
push 	high_guess_msg
jmp 	finish_round

;user guess lower number, print message and retry
guess_is_lower:
push 	low_guess_msg

finish_round:
call 	print_msg
add 	sp, 2
jmp 	main_game_loop

end_of_program:
;exit with return value 0
mov 	al,0
mov 	ah,4Ch		
int 	21h


;Function Description:
;	this function prints a given '$' terminated 
;	on the screen
;Input
;	arg0 - address of the message's begin
print_msg:
;set stack frame
push 	bp
mov 	bp, sp

;save reg content
push 	ax
push 	dx

;call print msg function
mov 	dx,[bp + 4]
mov 	ah,9h
int 	21h

;restore reg content
pop 	dx
pop 	ax

;destroy stack frame
mov 	sp, bp
pop 	bp

ret

;Function Description:
;	this function prints a given number
;	on the screen
;Input
;	arg0 - the number (decimal, not string) to print
print_number:
;set stack frame
push 	bp
mov 	bp, sp

push 	ax
push 	dx
push 	cx

mov 	cx, 0
mov 	ax,[bp + 4]

store_number_digits_loop:
inc 	cx
mov 	dx, 10
div 	dl

;push digit's ascii value on stack
mov 	dx, 0
mov 	dl, ah
add 	dl, '0'
push 	dx

cmp 	al, 0
je 	print_digits
;ax = (int)(ax / 10)
mov 	ah, 0
jmp 	store_number_digits_loop



;print digit by digit from most significant digit
;by poping the digits from the stack
print_digits:
mov 	ah, 2h
;pop the digits and print them
print_digits_loop:
pop 	dx
int 	21h
loop 	print_digits_loop

pop 	cx
pop 	dx
pop 	ax

;destroy stack frame
mov 	sp, bp
pop 	bp

ret

;Function Description:
;	this function reads 2 digits number from keyboard
;	and return it's decimal value
;Output
;	ax = the number

read_two_digits_number:
;set stack frame
push 	bp
mov 	bp, sp

;we need one word local var 'num'
sub 	sp,2

;num=0
mov 	word [bp - 2], 0

;read fisrt digit from keyboard
mov 	ah,1
int 	21h

;num = digit value
sub 	al,'0'
mov 	[bp - 2], al

;num = num*10 since we read the first digit out of two
mov 	ax,10
mul 	word [bp - 2]
mov 	[bp - 2], al

;read second digit from keyboard
mov 	ah,1
int 	21h

;num = num + digit value
sub 	al,'0'
add 	[bp - 2], al

;ax = number corespondant to the two digits number
mov 	ax, 0
mov 	al,[bp - 2]

;destroy stack frame
mov 	sp, bp
pop 	bp

ret

;---- Pre defined messages ----
start_msg 			db "I selected a random number between 0 and 99.",0Dh,0Ah,'$'
guess_request_msg	db "Please enter your guess: $"
high_guess_msg		db 0Dh,0Ah,"Your number is higher than mine.",0Dh,0Ah,'$'
low_guess_msg		db 0Dh,0Ah,"Your number is lower than mine.",0Dh,0Ah,'$'
win_msg_prefix		db 0Dh,0Ah,"You win! Try count: $"
win_msg_suffix		db '.',0Dh,0Ah,'$'

;---- Global variables ----
random_number		db 00h
guess_counter  		db 00h